package com.lizard.schedule.manager;

import android.text.TextUtils;

import com.android.volley.VolleyError;
import com.lizard.schedule.R;
import com.lizard.schedule.manager.observer.ObserverManager;
import com.lizard.schedule.net.http.consts.ReturnCode;
import com.lizard.schedule.net.http.request.HttpRequestManager;
import com.lizard.schedule.net.http.request.HttpResponseListener;
import com.lizard.schedule.net.http.request.bean.LoginRequest;
import com.lizard.schedule.net.http.request.bean.ScheduleSync.ScheduleSyncItem;
import com.lizard.schedule.net.http.request.bean.ThirdLoginRequest;
import com.lizard.schedule.net.http.request.bean.ThirdVerifyRequest;
import com.lizard.schedule.net.http.response.bean.LoginResponse;
import com.lizard.schedule.net.http.response.bean.ThirdVerifyResponse;
import com.lizard.schedule.persistence.db.table.ScheduleTbl;
import com.lizard.schedule.persistence.sharedpreferences.AccountPref;
import com.lizard.schedule.utils.encrypt.MD5Util;
import com.lizard.schedule.widget.ScheduleToast;

/**
 * 账户管理类
 */
public class AccountManager {

    /**
     * 登录方式：无记录
     */
    public static final int LOGIN_TYPE_NO_RECORD = 1;
    /**
     * 登录方式：非注册用户(单机)
     */
    public static final int LOGIN_TYPE_NOUSER = 2;
    /**
     * 登录方式：注册用户（包括第三方登录）
     */
    public static final int LOGIN_TYPE_USER = 3;

    private static AccountManager instance;
    /**
     * 当前用户名，若为null则表示非注册用户(单机用户)
     */
    private String mUsername;

    /**
     * 用户名对应的16位md5值
     */
    private String mUsernameMD5L16;

    private String mToken;

    /**
     * 当前用户登录方式
     */
    private int mLoginType = LOGIN_TYPE_NO_RECORD;

    /**
     * 第三方登录方式
     */
    private int mThirdLoginType = 0;

    /**
     * 当前用户最近一次记录在内存中的编辑计划的时间
     */
    private long mLastEditScheduleTime = 0;

    /**
     * 用户最近一次添加计划界面当存在未提交数据时的返回时间
     */
    private long mLastAddScheduleUnsubmitBackTime = 0;

    /**
     * 用户最近一次添加计划界面返回后的未提交时间
     */
    private long mLastAddScheduleTimeForBack = 0;

    /**
     * 用户最近一次添加计划界面返回后的未提交文本内容
     */
    private String mLastAddScheduleContentForBack;

    private AccountManager() {
        reset();
    }

    public static AccountManager getInstance() {
        if (instance == null) {
            synchronized (AccountManager.class) {
                if (instance == null) {
                    instance = new AccountManager();
                }
            }
        }
        return instance;
    }

    /**
     * 获取最近一次登录方式
     *
     * @return
     */
    public int getLoginType(){
        return mLoginType;
    }

    /**
     * 获取最近一次登录方式如果是第三方登录时的类型
     *
     * @return
     */
    public int getThirdLoginType(){
        return mThirdLoginType;
    }

    /**
     * 获取最近一次登录用户名
     *
     * @return
     */
    public String getUsername() {
        return TextUtils.isEmpty(mUsername) ? null : mUsername;

    }

    public String getToken(){
        return mToken;
    }

    /**
     * 获取用户名的16位md5值
     *
     * @return
     */
    public String getmUsernameMD5L16(){
        if(mUsernameMD5L16 == null){
            if(!TextUtils.isEmpty(mUsername)){
                mUsernameMD5L16 = MD5Util.md5EncryptL16(mUsername);
            }
        }
        return mUsernameMD5L16;
    }

    /**
     * 内存缓存重置
     */
    private void reset(){
        mUsername = null;
        mToken = null;
        mUsernameMD5L16 = null;
        mLoginType = LOGIN_TYPE_NO_RECORD;
        mThirdLoginType = 0;
        mLastEditScheduleTime = 0;
        mLastAddScheduleUnsubmitBackTime = 0;
        mLastAddScheduleTimeForBack = 0;
        mLastAddScheduleContentForBack = null;
    }

    /**
     * 账户退出登录的所有本地数据缓存等重置操作
     */
    public void logOut(){
        AccountPref.getInstance().clear();                  // 账户对应SharedPreference清空数据
        reset();                                            // 账户管理类数据重置
        ScheduleLocalIdGenerator.getInstance().unInit();    // id生成器注销
        ScheduleSyncManager.getInstance().clear();          // 同步队列清空掉
    }

    /**
     * 从本地缓存获取最近一次登录信息存到内存缓存, 并进行免登录初始化
     */
    public void checkOutLastLoginInfoFromLocal(){
        mLoginType = AccountPref.getInstance().getLoginType();
        mThirdLoginType = AccountPref.getInstance().getThirdLoginType();
        String userName = AccountPref.getInstance().getUsername();
        mUsername = TextUtils.isEmpty(userName) ? null : userName;
        String pwd = AccountPref.getInstance().getPwd();
        String token = AccountPref.getInstance().getToken();
        mToken = TextUtils.isEmpty(token) ? null : token;

        if(AccountManager.getInstance().getLoginType() != AccountManager.LOGIN_TYPE_NO_RECORD){
            // 免登陆初始化
            loginInit(mUsername, pwd, token, mThirdLoginType);
        }
    }

    /**
     * 登录初始化
     *
     * @param username 非注册用户传null
     * @param pwd       非注册用户传null
     * @param token
     * @param thirdLoginType 如果是第三方登录的登录方式
     */
    public void loginInit(String username, String pwd, String token, int thirdLoginType){
        if(TextUtils.isEmpty(username)){
            mLoginType = LOGIN_TYPE_NOUSER; // 记录登录类型为非注册用户
            mThirdLoginType = 0;
            mUsername = null;
            mUsernameMD5L16 = null;
            mToken = null;
            AccountPref.getInstance().saveLoginType(mLoginType);
        } else{

            mLoginType = LOGIN_TYPE_USER;
            mThirdLoginType = thirdLoginType;
            mUsername = username;
            mToken = token;
            // 用户对应的表判断是否存在并创建
            ScheduleTbl.getInstance().createTbl(getmUsernameMD5L16());
            AccountPref.getInstance().saveLoginType(mLoginType);
            AccountPref.getInstance().saveLoginAccount(username, pwd, token);
            AccountPref.getInstance().saveThirdLoginType(mThirdLoginType);
        }

        // id生成器初始化
        ScheduleLocalIdGenerator.getInstance().init();
    }

    /**
     * 从内存获取最近一次记录在内存中的编辑计划的时间
     *
     * @return
     */
    public long getLastEditScheduleTime(){
        return mLastEditScheduleTime;
    }

    /**
     * 保存最近一次记录在内存中的编辑计划的时间到内存(进程回收后不再保留)
     *
     * @param time
     */
    public void setLastEditScheduleTime(long time){
        mLastEditScheduleTime = time;
    }

    /**
     * 从内存获取用户最近一次添加计划界面当存在未提交数据时的返回时间
     *
     * @return
     */
    public long getLastAddScheduleUnsubmitBackTime() {
        return mLastAddScheduleUnsubmitBackTime;
    }

    /**
     * 保存用户最近一次添加计划界面当存在未提交数据时的返回时间到内存(进程回收后不再保留)
     *
     * @param time
     */
    public void setLastAddScheduleUnsubmitBackTime(long time) {
        mLastAddScheduleUnsubmitBackTime = time;
    }

    /**
     * 从内存获取用户最近一次添加计划界面返回后的未提交时间
     *
     * @return
     */
    public long getLastAddScheduleTimeForBack() {
        return mLastAddScheduleTimeForBack;
    }

    /**
     * 保存用户最近一次添加计划界面返回后的未提交时间到内存(进程回收后不再保留)
     *
     * @param time
     */
    public void setLastAddScheduleTimeForBack(long time) {
        mLastAddScheduleTimeForBack = time;
    }

    /**
     * 从内存获取用户最近一次添加计划界面返回后的未提交文本内容
     *
     * @return
     */
    public String getLastAddScheduleContentForBack() {
        return mLastAddScheduleContentForBack;
    }

    /**
     * 保存用户最近一次添加计划界面返回后的未提交文本内容到内存(进程回收后不再保留)
     *
     * @param content
     */
    public void setLastAddScheduleContentForBack(String content) {
        mLastAddScheduleContentForBack = content;
    }

    /**
     * 第三方登录的账户静默验证
     * 任何需要静默验证的地方都可调用此类
     * 这里在请求返回时做了通用处理：1、验证成功后更新本地和内存中的账户数据 2、验证失败后toast提示并通知退出
     * 因此外部做回调时要避免重复做这些动作
     *
     * @param listener 请求回调
     */
    public void verifyAccountThird(final HttpResponseListener<ThirdVerifyResponse> listener){
        final String username = AccountManager.getInstance().getUsername();
        final int thirdLoginType = AccountManager.getInstance().getThirdLoginType();
        if(!TextUtils.isEmpty(username) && thirdLoginType != 0){
            final String pwd = AccountPref.getInstance().getPwd();

            ThirdVerifyRequest request = new ThirdVerifyRequest();
            request.setUsername(username);
            request.setPassword(pwd);
            HttpRequestManager.getInstance().request(request, new HttpResponseListener<ThirdVerifyResponse>() {
                @Override
                public void onErrorResponse(VolleyError volleyError) {
                    if(listener != null){
                        listener.onErrorResponse(volleyError);
                    }
                }

                @Override
                public void onResponse(ThirdVerifyResponse response) {
                    if(ReturnCode.SUCCESS.equals(response.getReturnCode())){    // 成功
                        // 验证成功
                        AccountManager.getInstance().loginInit(username, pwd, response.getToken(), thirdLoginType);
                    } else {    // 失败
                        // 验证失败 通知退出登录
                        ObserverManager.getInstance().notifyLogouts();
                        ScheduleToast.makeScheduleToastS(R.string.account_error_relogin).show();
                    }

                    if(listener != null){
                        listener.onResponse(response);
                    }
                }
            });
        }
    }

    /**
     * 账户静默验证
     * 任何需要静默验证的地方都可调用此类
     * 这里在请求返回时做了通用处理：1、验证成功后更新本地和内存中的账户数据 2、验证失败后toast提示并通知退出
     * 因此外部做回调时要避免重复做这些动作
     *
     * @param listener 请求回调
     */
    public void verifyAccount(final HttpResponseListener<LoginResponse> listener){
        final String username = AccountManager.getInstance().getUsername();
        if(!TextUtils.isEmpty(username)){
            final String pwd = AccountPref.getInstance().getPwd();

            LoginRequest request = new LoginRequest();
            request.setUsername(username);
            request.setPassword(pwd);
            HttpRequestManager.getInstance().request(request, new HttpResponseListener<LoginResponse>() {
                @Override
                public void onErrorResponse(VolleyError volleyError) {
                    if(listener != null){
                        listener.onErrorResponse(volleyError);
                    }
                }

                @Override
                public void onResponse(LoginResponse response) {
                    if(ReturnCode.SUCCESS.equals(response.getReturnCode())){    // 成功
                        // 验证成功
                        AccountManager.getInstance().loginInit(username, pwd, response.getToken(), 0);
                    } else {    // 失败
                        // 验证失败 通知退出登录
                        ObserverManager.getInstance().notifyLogouts();
                        ScheduleToast.makeScheduleToastS(R.string.account_error_relogin).show();
                    }

                    if(listener != null){
                        listener.onResponse(response);
                    }
                }
            });
        }
    }

}
